package ic.ast.decl;

import ic.ast.Visitor;
import ic.types.TypeTable;

/**
 * Primitive data type AST node.
 * 
 */
public class PrimitiveType extends Type {

	private DataType type;

	public Object accept(Visitor visitor) throws Exception {
		return visitor.visit(this);
	}

	/**
	 * Constructs a new primitive data type node.
	 * 
	 * @param line
	 *            Line number of type declaration.
	 * @param type
	 *            Specific primitive data type.
	 */
	public PrimitiveType(int line, DataType type) {
		super(line);
		this.type = type;
	}

	public String getDisplayName() {
		return type.toString();
	}

    @Override
    public String getOutputName() {
        return type.getOutputName();
    }

    @Override
    public Type clone(int newDimension) {
        Type newType = new PrimitiveType(getLine(), type);
        for(int i = 0; i < newDimension; i++) {
            newType.incrementDimension();
        }
        return newType;
    }

    @Override
    public boolean subTypeOf(Type otherType) {
        if (this.type == DataType.VOID && (otherType instanceof ClassType || otherType.getArrayDimension() > 0 || otherType == TypeTable.getType("string"))) {
            return true;
        }

        return this == otherType;
    }

    @Override
    public boolean equals(Object other) {
        return (other instanceof PrimitiveType) &&
                this.type == ((PrimitiveType)other).type &&
                this.getArrayDimension() == ((PrimitiveType)other).getArrayDimension();
    }

    /**
	 * Enumerated type listing the primitive data types.
	 */
	public enum DataType {

		INT("int", "integer"),
		BOOLEAN("boolean"), 
		STRING("string"), 
		VOID("void");
		
		private String description;
        private String outputName;

		private DataType(String description) {
			this(description, description);
		}

        private DataType(String description, String outputName) {
            this.description = description;
            this.outputName = outputName;
        }

		@Override
		public String toString() {
			return description;
		}

        public String getOutputName() {
            return outputName;
        }
    }

}
